package knowse.app.parser;

import java.io.IOException;
import java.util.ArrayList;

import knowse.app.FetchData;
import knowse.app.daos.ChangeDAO;
import knowse.app.daos.ChangeDataObject;
import knowse.app.daos.CommitDAO;
import knowse.app.daos.CommitDataObject;
import knowse.app.daos.LogDAO;
import knowse.app.daos.LogDataObject;
import knowse.app.daos.ProjectDAO;
import knowse.app.daos.TestStatusDAO;
import knowse.app.daos.TestStatusDataObject;
import knowse.app.daos.TestStatusDetailDAO;
import knowse.app.daos.TestStatusDetailDataObject;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class Parser {
	
	private final String TAG = "Parser";
	private final String hostUrl ="http://cse-212240.cse.chalmers.se/feldt/courses/agile2012/data/knowse/";
	private final String contentsFileUrl= hostUrl + "contents.txt";
	String knowsePrefix ="knowse";
	FetchData fd;
	ArrayList<CommitDataObject> commitDataObjects;
	ArrayList<ChangeDataObject> changeDataObjects;
	
	public Parser(){
		fd = new FetchData();
		commitDataObjects = new ArrayList<CommitDataObject>();
		changeDataObjects = new ArrayList<ChangeDataObject>();
		fetchContentsFile();
		
	}
	
	private void fetchContentsFile(){
		try{
			ArrayList<TestStatusDetailDataObject> tsdd = new ArrayList<TestStatusDetailDataObject>();
			String contentsFileString = fd.fetchData(contentsFileUrl);
			
			String[] contents = contentsFileString.split("\n");
			String[] filenames = new String[contents.length];
			
			for(int i = 0; i < contents.length; i++){
				String tmp = contents[i];
				String tmp2 = tmp.substring(0, tmp.indexOf(","));
				if(tmp2.startsWith(knowsePrefix)){
					filenames[i] = tmp2;
				}
			}
			
			//fetch and parse projects
			ProjectDAO p = new ProjectDAO();
			p.store();
			
			//fetch the knowse_ruby_test.csv
			String knowse_ruby_test_csv_url = hostUrl + filenames[1];
			String knowse_ruby_test_csv_String = (String)fd.fetchCSV(knowse_ruby_test_csv_url);			
			//parse knowse_ruby_test.csv
			parseAndStoreKnowSERubyTestBatch(knowse_ruby_test_csv_String);

			//For each ruby_test.json
				//Fetch
				//Parse
			for(int i = 3; i < filenames.length-1; i++){
				JSONArray jArr = fd.fetchJSON(hostUrl+filenames[i]);
				for(int j = 0; j < jArr.length(); j++){
					try {
						JSONObject jObj = jArr.getJSONObject(j);
						TestStatusDetailDataObject tdo = new TestStatusDetailDataObject(jObj, filenames[i]);
						tsdd.add(tdo);
					} catch (JSONException e) {
						Log.e(TAG, e.getMessage());
					} catch (Exception e) {
						Log.e(TAG, e.getMessage());
					}
				}
			}
			storeTestStatusDetailDataObjectBatch(tsdd);
			
			//Fetch knowse_git_log.json
				//parse log
					//foreach log parse commit
						//foreach commit parse change
			JSONObject jObj=fd.fetchJSON2Object(hostUrl+filenames[2]);
			
			try {
				LogDataObject ldo = new LogDataObject(jObj);
				parseLog(ldo);
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
			}
			
		}catch(IOException e){
			Log.e(TAG, e.getMessage());
		}
	}

	/*
	 * Parse and store the data in the commit log.
	 */
	public void parseLog(LogDataObject ldo){
		try{
			LogDAO tdao=new LogDAO();
			tdao.store(ldo);
			Log.d(TAG, "LogDataObject stored.");
			for(int i=0;i<ldo.getCommits().size();i++){
				CommitDataObject cdo=ldo.getCommits().get(i);
				cdo.setCommitID(i+1);
				cdo.setLogID(i);
				commitDataObjects.add(cdo);
				parseCommit(cdo,i, i+1);
			}			
			CommitDAO cdo = new CommitDAO();
			ChangeDAO chdao = new ChangeDAO();
			
			cdo.storeTrans(commitDataObjects);
			Log.d(TAG, "CommitDataObjects stored.");
			chdao.storeTrans(changeDataObjects);
			Log.d(TAG, "ChangeDataObjects stored.");
		}catch(Exception e)
		{
			Log.e(TAG, e.getMessage());
		}
	}
	
	/*
	 * Parse commits
	 */
	public void parseCommit(CommitDataObject cdo, int logid, int commitid){
		for(int j=0;j<cdo.getChanges().size();j++){
			ChangeDataObject temp = cdo.getChanges().get(j);
			temp.setCommitID(commitid);
			changeDataObjects.add(temp);
		}
	}
	
	
	/*
	 * Fetch and batch store test status lines.
	 */
	public void parseAndStoreKnowSERubyTestBatch(String rubyTestFile){
		try{
			TestStatusDAO t = new TestStatusDAO();
			ArrayList<TestStatusDataObject> arr = new ArrayList<TestStatusDataObject>();
			String[] rubyTestLine = rubyTestFile.split("\n");
			for(int i = 1; i < rubyTestLine.length; i++){
				TestStatusDataObject tdo = new TestStatusDataObject(rubyTestLine[i]);
				arr.add(tdo);
			}
			//store
			t.storeTrans(arr);
			Log.d(TAG, "TestStatusDataObjects stored.");
		}catch(Exception e){
			Log.d(TAG, e.getMessage());
		}

	}
	
	/*
	 * Batch store a list of TestStatusDetailDataObjects.
	 */
	private void storeTestStatusDetailDataObjectBatch(ArrayList<TestStatusDetailDataObject> tsdd){
		try{
			TestStatusDetailDAO t = new TestStatusDetailDAO();
			t.storeTrans(tsdd);
			Log.d(TAG, "TestStatusDetailDataObjects stored.");
		}catch(Exception e){
			Log.d(TAG, e.getMessage());
		}
	}
	
	
	/**********************
	 * 
	 * Deprecated Methods
	 * 
	 **********************/
	
	@Deprecated
	public void parseKnowSERubyTest(String rubyTestFile){
		try{
			TestStatusDAO t = new TestStatusDAO();
			String[] rubyTestLine = rubyTestFile.split("\n");
			for(int i = 1; i < rubyTestLine.length; i++){
				TestStatusDataObject tdo = new TestStatusDataObject(rubyTestLine[i]);
				t.store(tdo);
			}
		}catch(Exception e){
			Log.d(TAG, e.getMessage());
		}

	}
	
	@Deprecated
	public void parseKnowSETestProblem(JSONObject jObj, String filename){
		try {
			TestStatusDetailDataObject tdo = new TestStatusDetailDataObject(jObj, filename);
			TestStatusDetailDAO tdao = new TestStatusDetailDAO();
			tdao.store(tdo);
		}catch (JSONException e) {
			Log.e(TAG, e.getMessage());
		}catch(Exception e){
			Log.e(TAG, e.getMessage());
		}
	}
	
	
	/*
	 * Parse and store Commits
	 */
	@Deprecated
	public void parseCommit(CommitDataObject cdo, Integer logid, Integer commitid){
		try{
			CommitDAO cdao=new CommitDAO();
			cdao.store(cdo, logid);
			// TODO change the logic to DAO or parse here?
			//changes
			for(int j=0;j<cdo.getChanges().size();j++){
				ChangeDataObject temp = cdo.getChanges().get(j);
				parseChange(temp,commitid);			
			}
			
			
		}catch(Exception e)
		{
			Log.e(TAG, e.getMessage());
		}
	}
	
	/*
	 * Parse and store Changes
	 */
	@Deprecated
	public void parseChange(ChangeDataObject cdo, Integer commitid){
		try{
			ChangeDAO cdao=new ChangeDAO();
			cdao.store(cdo, commitid);
		}catch(Exception e){
			Log.e(TAG, e.getMessage());
		}
	}
	
}
